package licode.unisop.authcenter.application.executor;

import licode.unisop.authcenter.application.info.RealmUserGroupOfPlatPageIn;
import licode.unisop.authcenter.application.info.RealmUserGroupQueryPageIn;
import licode.unisop.authcenter.application.info.RealmUserQueryPageIn;
import licode.unisop.authcenter.application.info.UserLookupIn;
import licode.unisop.authcenter.exception.CenterErrorCode;
import licode.unisop.platform.client.api.SiPlatformQueryService;
import licode.unisop.provider.conf.SiAssetState;
import licode.unisop.provider.info.*;
import licode.unisop.provider.utils.StrUtil;
import licode.unisop.provider.vo.*;
import licode.unisop.realm.client.api.SiUserQueryService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 定义统一认证平台中心领域用户查询相关接口
 *
 * @author licode
 */
@Service
public class CenterRealmUserQueryExecutor {
    @Resource
    private SiUserQueryService siUserQueryService;

    @Resource
    private SiPlatformQueryService siPlatformQueryService;

    /**
     * 分页查询领域用户信息
     */
    public SiPageResult<SiUser> queryPage(RealmUserQueryPageIn req) {
        if (null != req.getState() && req.getState() < 0) {
            req.setState(null);
        }

        if (StrUtil.isBlank(req.getRealmId())) {
            if (StrUtil.isBlank(req.getPlatformId())) {
                throw CenterErrorCode.LACK_OF_PLATFORM_ID.buildException();
            }
            SiPlatform platform = siPlatformQueryService.lookupPlatform(SiPlatIdFind.builder()
                    .platformId(req.getPlatformId()).build());
            if (null == platform) {
                throw CenterErrorCode.PLATFORM_IS_DONT_EXIST.buildException();
            } else if (StrUtil.isBlank(platform.getRealmId())) {
                throw CenterErrorCode.PLATFORM_DONT_BIND_REALM.buildException();
            }

            req.setRealmId(platform.getRealmId());
        }

        return siUserQueryService.findPage(UserPageInfo.builder()
                .current(req.getCurrent())
                .pageSize(req.getPageSize())
                .realmId(req.getRealmId())
                .userName(req.getName())
                .groups(req.getGroups())
                .filterGroups(req.getFilterGroups())
                .state(req.getState())
                .build());
    }

    public SiPageResult<SiPlatform> queryAssignPlatformPage(SiRealmAssignPlatPageIn req) {
        SiPageResult<SiRealmPlatform> result = siUserQueryService.findRealPlatform(req);
        if (null == result || null == result.getData() || result.getData().isEmpty()) {
            return null;
        } else {
            Map<String, SiPlatform> platMap;
            SiPageResult<SiPlatform> plats;
            plats = siPlatformQueryService.findPlatformPage(PlatPageInfo.builder()
                    .current(1)
                    .pageSize(result.getData().size())
                    .platformIds(result.getData().stream()
                            .map(SiRealmPlatform::getPlatformId)
                            .collect(Collectors.toList()))
                    .build());
            if (null != plats && plats.getData() != null && !plats.getData().isEmpty()) {
                platMap = plats.getData().stream().collect(Collectors.toMap(SiPlatform::getId, Function.identity()));
            } else {
                platMap = new HashMap<>();
            }

            plats = new SiPageResult<>();
            plats.setCurrent(result.getCurrent());
            plats.setPageSize(result.getPageSize());
            plats.setCount(result.getCount());
            plats.setTotal(result.getTotal());
            plats.setData(new ArrayList<>());

            for (SiRealmPlatform item : result.getData()) {
                SiPlatform platform = platMap.get(item.getPlatformId());
                if (null == platform) {
                    platform = new SiPlatform();
                    platform.setId(item.getPlatformId());
                    platform.setName("--");
                    platform.setState(SiAssetState.AT_DELETED);
                }
                plats.getData().add(platform);
            }

            return plats;
        }
    }

    public SiPageResult<SiPlatform> queryCanAssignPlatformPage(SiRealmCanAssignPlatPageIn req) {
        SiPageResult<SiPlatform> plats;
        plats = siPlatformQueryService.findPlatformPage(PlatPageInfo.builder()
                .current(req.getCurrent())
                .pageSize(req.getPageSize())
                .name(req.getName())
                .build());
        if (null == plats || null == plats.getData() || plats.getData().isEmpty()) {
            return null;
        } else {
            if (null == req.getFilterGroups() || req.getFilterGroups().isEmpty()) {
                return plats;
            } else {
                List<String> assignPlatIds;
                List<SiRealmPlatform> platList;
                // 根据分组找到已经分配的平台
                SiPageResult<SiRealmPlatform> assignPlat;
                assignPlat = siUserQueryService.findRealPlatform(SiRealmAssignPlatPageIn.builder()
                        .current(1L)
                        .pageSize(Integer.valueOf(plats.getData().size()).longValue())
                        .realmId(req.getRealmId())
                        .groups(req.getFilterGroups())
                        .build());
                platList = siUserQueryService.findRealPlatformOther(SiRealmPlatformOtherIn.builder()
                        .realmId(req.getRealmId()).build());

                if (null != assignPlat && null != assignPlat.getData() && !assignPlat.getData().isEmpty()) {
                    platList.addAll(assignPlat.getData());
                }

                if (!platList.isEmpty()) {
                    assignPlatIds = platList.stream()
                            .map(SiRealmPlatform::getPlatformId)
                            .collect(Collectors.toList());
                } else {
                    assignPlatIds = new ArrayList<>();
                }

                for (SiPlatform item : plats.getData()) {
                    if (null == item.getProps()) {
                        item.setProps(new SiProps());
                    }

                    if (assignPlatIds.contains(item.getId())) {
                        item.getProps().addProp("exist", 1);
                    } else {
                        item.getProps().addProp("exist", 0);
                    }
                }

                return plats;
            }

        }
    }

    /**
     * 查询指定领域用户信息
     */
    public SiUser lookup(UserLookupIn req) {
        return siUserQueryService.lookupUserById(UserIdInfo.builder()
                .realmId(req.getRealmId())
                .userId(req.getUserId())
                .build());
    }

    /**
     * 按层次分页读取领域用户的分组，根据传入的平台ID过滤掉已经加入平台的分组
     * 此方法会根据parentId查询其子分组信息
     */
    public SiUser queryUserGroupLevel(RealmUserGroupQueryPageIn req) {
        return null;
    }

    /**
     * 分页查询分配给平台的领域用户分组
     */
    public List<SiUserGroup> queryGroupOfPlatformList(RealmUserGroupOfPlatPageIn req) {
        SiPlatform platform = siPlatformQueryService.lookupPlatform(SiPlatIdFind.builder()
                .platformId(req.getPlatformId()).build());

        if (null == platform || StrUtil.isBlank(platform.getRealmId())) {
            return null;
        } else {
            return siUserQueryService.findRealmGroupsOfPlatform(UserGroupQueryIn.builder()
                    .realmId(platform.getRealmId())
                    .platformId(req.getPlatformId())
                    .build());
        }
    }

    public List<SiUserGroup> queryGroupOfRealmList(SiRealmFind req) {
        if (StrUtil.isBlank(req.getRealmId())) {
            return null;
        } else {
            SiPageResult<SiUserGroup> page;
            page = siUserQueryService.findUserGroupPage(UserGroupQueryPageIn.builder()
                    .current(1L)
                    .pageSize(999L)
                    .realmId(req.getRealmId())
                    .build());
            return null == page ? null : page.getData();
        }
    }

    public SiAccountSet findAccount(UserIdInfo idFind) {
        return siUserQueryService.findAccount(idFind);
    }
}
